package com.fanxuankai.boot.upload;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fanxuankai.boot.upload.dao.FileDao;
import com.fanxuankai.boot.upload.dao.JobDao;
import com.fanxuankai.boot.upload.domain.File;
import com.fanxuankai.boot.upload.domain.Job;
import com.fanxuankai.boot.upload.dto.JobDTO;
import com.fanxuankai.boot.upload.vo.FileVO;
import com.fanxuankai.boot.upload.vo.JobVO;
import com.fanxuankai.commons.domain.PageRequest;
import com.fanxuankai.commons.domain.PageResult;
import com.fanxuankai.commons.domain.Result;
import com.fanxuankai.commons.extra.mybatis.util.MybatisPlusPageUtils;
import com.fanxuankai.commons.extra.mybatis.util.QueryHelper;
import com.fanxuankai.commons.util.BeanUtils;
import com.fanxuankai.commons.util.ResultUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author fanxuankai
 */
@RestController
@RequestMapping("${fxk.upload.url:upload}")
public class UploadController {
    @Resource
    private Uploader uploader;
    @Resource
    private JobDao jobDao;
    @Resource
    private FileDao fileDao;

    @PostMapping
    public Result<Long> upload(@RequestPart("file") MultipartFile multipartFile, String handler)
            throws IOException {
        if (multipartFile.isEmpty()) {
            return ResultUtils.fail("空文件");
        }
        if (!uploader.canHandle(handler)) {
            return ResultUtils.fail("无处理器");
        }
        return ResultUtils.ok(uploader.createJob(multipartFile, handler));
    }

    @GetMapping("page")
    public Result<PageResult<JobVO>> page(PageRequest pageRequest, JobDTO dto) {
        Page<Job> page = jobDao.page(MybatisPlusPageUtils.convert(pageRequest),
                QueryHelper.getQueryWrapper(Job.class, dto));
        Set<Long> fileIds = page.getRecords()
                .stream()
                .map(Job::getFileId)
                .collect(Collectors.toSet());
        Map<Long, File> fileMap = fileDao.listByIds(fileIds)
                .stream()
                .collect(Collectors.toMap(File::getId, Function.identity()));
        return ResultUtils.ok(MybatisPlusPageUtils.convert(page, job -> {
            JobVO vo = BeanUtils.copyProperties(job, JobVO.class);
            vo.setProgress(jobDao.calcProgress(job.getId()));
            Optional.ofNullable(fileMap.get(job.getFileId()))
                    .map(file -> BeanUtils.copyProperties(file, FileVO.class))
                    .ifPresent(vo::setFile);
            return vo;
        }));
    }

    @GetMapping("{id}")
    public Result<JobVO> get(@PathVariable Long id) {
        Job job = jobDao.getById(id);
        JobVO vo = BeanUtils.copyProperties(job, JobVO.class);
        Optional.ofNullable(fileDao.getById(job.getFileId()))
                .map(file -> BeanUtils.copyProperties(file, FileVO.class))
                .ifPresent(vo::setFile);
        vo.setProgress(jobDao.calcProgress(job.getId()));
        return ResultUtils.ok(vo);
    }
}